<template>
  <div class="timeline-story-scrollspy" ref="parent" @scroll="onScroll">
    <div
      class="scrollspy__nav__prev"
      v-show="showNavPrev"
      @click="scrollBtnHandller('prev')"
    ></div>
    <ul>
      <li
        v-for="(label, idx) in list"
        :key="label.id"
        class="timeline-story-scrollspy__item"
        :class="{ 'is-active': activeIdx == idx }"
        @click="scrollToIdx(idx)"
      >
        {{ label.title }}
      </li>
    </ul>
    <div
      class="scrollspy__nav__next"
      v-show="showNavNext"
      @click="scrollBtnHandller('next')"
    ></div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'

// 定义组件名称
defineOptions({
  name: 'TimelineStoryScrollspy'
})

const props = defineProps<{
  list: any[]
  activeIdx: number
}>()

// 定义 emits
const emit = defineEmits<{
  scrollToIdx: [idx: number]
}>()

// 响应式数据
const scrollTop = ref(0)
const scrollHeight = ref(0)
const wrapperHeight = ref(0)

// 模板引用
const parent = ref<HTMLElement | null>(null)

// 计算属性
const showNavPrev = computed(() => {
  return scrollTop.value > 0
})

const showNavNext = computed(() => {
  return scrollHeight.value - scrollTop.value > wrapperHeight.value
})

// 监听器
watch(() => props.activeIdx, () => {
  centerTheList()
})

// 方法
const scrollToIdx = (idx: number) => {
  emit('scrollToIdx', idx)
}

const centerTheList = () => {
  const parentEl = parent.value
  if (!parentEl) return

  const buttons = parentEl.querySelectorAll('.timeline-story-scrollspy__item')
  const currentTab = buttons[props.activeIdx] as HTMLElement
  if (!currentTab) return

  const tabTop = currentTab.getBoundingClientRect().top
  const parentTop = parentEl.getBoundingClientRect().top
  const center = parentEl.clientHeight / 2
  parentEl.scrollTop -= center - tabTop + parentTop
}

const onScroll = () => {
  const parentEl = parent.value
  if (!parentEl) return

  scrollTop.value = parentEl.scrollTop
  scrollHeight.value = parentEl.scrollHeight
  wrapperHeight.value = parentEl.clientHeight
}

const scrollBtnHandller = (dir: string) => {
  const parentEl = parent.value
  if (!parentEl) return

  if (dir === 'next') {
    parentEl.scrollTop += 9999
  } else {
    parentEl.scrollTop -= 9999
  }
}
</script>

<style lang="scss" scoped>
.timeline-story-scrollspy {
  padding: 10px 18px 15px 0;
  background-color: #f8f9fa;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  border-radius: 0px 4px 4px 0px;
  max-height: 300px;
  overflow-y: scroll;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;

  &::-webkit-scrollbar {
    display: none;
  }

  &__item {
    font-size: 12px;
    font-weight: 500;
    line-height: 1.3;
    color: #666;
    margin: 8px 0;
    cursor: pointer;
    display: flex;
    align-items: center;

    &::before {
      content: '';
      width: 9px;
      height: 1px;
      margin-right: 11px;
    }

    &.is-active {
      font-size: 14px;
      font-weight: 600;
      line-height: 1.2;
      color: #0066cc;

      &::before {
        background-color: #000;
        margin-right: 4px;
      }
    }
  }

  .scrollspy__nav__prev,
  .scrollspy__nav__next {
    position: absolute;
    left: 0;
    width: 100%;
    height: 25px;
    background-color: #f8f9fa;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;

    &::after {
      content: '';
      width: 24px;
      height: 24px;
      background-image: url('');
      background-size: contain;
      background-repeat: no-repeat;
      background-position: center;

      @media (max-width: 1023.98px) {
        width: 14px;
        height: 14px;
      }
    }
  }

  .scrollspy__nav__prev {
    box-shadow: 0px 4px 17px rgba(0, 0, 0, 0.22);
    top: -1px;

    &::after {
      transform: rotateZ(270deg);
    }
  }

  .scrollspy__nav__next {
    box-shadow: 0px -4px 17px rgba(0, 0, 0, 0.22);
    bottom: -1px;

    &::after {
      transform: rotateZ(90deg);
    }
  }
}
</style>